import os
import re
import subprocess
import platform
import traceback
from .utils import get_startupinfo

class FrameOperations:
    def __init__(self):
        pass
    
    def create_video(self):
        """从帧创建视频"""
        try:
            self.log_message.emit(f"开始从帧创建视频...")
            
            # 获取帧列表
            frame_files = sorted([f for f in os.listdir(self.frames_dir) if f.endswith('.jpg') or f.endswith('.png')])
            
            if not frame_files:
                self.log_message.emit("未找到帧图像")
                self.process_completed.emit(False, "未找到帧图像")
                return
            
            # 构建FFmpeg命令
            command = [self.ffmpeg_path]
            
            # 添加硬件加速选项
            if self.hardware_accel != "cpu":
                # 提取实际的硬件加速类型（去除描述文本）
                actual_accel = self.hardware_accel.split()[0] if " " in self.hardware_accel else self.hardware_accel
                command.extend(["-hwaccel", actual_accel])
            
            # 添加输入帧率
            command.extend(["-framerate", str(self.fps)])
            
            # 添加输入模式
            frame_pattern = os.path.join(self.frames_dir, "%04d.jpg")
            if os.path.exists(os.path.join(self.frames_dir, "1.jpg")):
                frame_pattern = os.path.join(self.frames_dir, "%d.jpg")
            elif os.path.exists(os.path.join(self.frames_dir, "0.jpg")):
                frame_pattern = os.path.join(self.frames_dir, "%d.jpg")
            elif os.path.exists(os.path.join(self.frames_dir, "00000.jpg")):
                frame_pattern = os.path.join(self.frames_dir, "%05d.jpg")
            elif os.path.exists(os.path.join(self.frames_dir, "00001.jpg")):
                frame_pattern = os.path.join(self.frames_dir, "%05d.jpg")
            else:
                # 使用第一个文件的格式
                first_file = frame_files[0]
                name_part = os.path.splitext(first_file)[0]
                ext_part = os.path.splitext(first_file)[1]
                
                # 检测数字部分的格式
                if name_part.isdigit():
                    # 简单数字格式
                    frame_pattern = os.path.join(self.frames_dir, f"%{len(name_part)}d{ext_part}")
                else:
                    # 复杂格式，使用通配符
                    frame_pattern = os.path.join(self.frames_dir, f"*.{ext_part[1:]}")
            
            command.extend(["-i", frame_pattern])
            
            # 添加输出选项
            command.extend([
                "-c:v", "libx264",
                "-preset", "medium",
                "-crf", "23",
                "-pix_fmt", "yuv420p",  # 确保兼容性
                "-y",  # 覆盖已存在的文件
                self.output_video
            ])
            
            # 记录命令
            command_str = " ".join(f'"{item}"' if ' ' in str(item) or '\\' in str(item) else str(item) for item in command)
            self.log_message.emit(f"FFmpeg命令: {command_str}")
            
            # 创建无窗口进程
            startupinfo = get_startupinfo()
            
            # 启动进程
            process = subprocess.Popen(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                universal_newlines=True,
                startupinfo=startupinfo
            )
            
            # 读取输出并更新进度
            output = ""
            total_frames = len(frame_files)
            
            for line in process.stdout:
                output += line
                
                # 尝试从输出中提取当前帧
                frame_match = re.search(r"frame=\s*(\d+)", line)
                if frame_match:
                    current_frame = int(frame_match.group(1))
                    progress = min(int(current_frame / total_frames * 100), 100)
                    self.progress_updated.emit(progress)
                    
                # 输出日志
                self.log_message.emit(line.strip())
            
            # 等待进程完成
            return_code = process.wait()
            
            # 检查返回码
            if return_code == 0:
                self.log_message.emit(f"视频创建成功: {self.output_video}")
                self.process_completed.emit(True, self.output_video)
            else:
                self.log_message.emit(f"视频创建失败，返回码: {return_code}")
                self.process_completed.emit(False, f"视频创建失败，返回码: {return_code}")
            
        except Exception as e:
            self.log_message.emit(f"视频创建出错: {str(e)}")
            self.log_message.emit(traceback.format_exc())
            self.process_completed.emit(False, f"视频创建出错: {str(e)}")
    
    def extract_frames(self):
        """从视频中提取帧"""
        try:
            # 检查输入视频是否存在
            if not os.path.exists(self.input_video):
                self.log_message.emit(f"输入视频不存在: {self.input_video}")
                self.process_completed.emit(False, "输入视频不存在")
                return
            
            # 创建输出目录
            frames_dir = os.path.join(os.path.dirname(self.input_video), "frames")
            if not os.path.exists(frames_dir):
                os.makedirs(frames_dir)
            else:
                # 清空目录
                for file in os.listdir(frames_dir):
                    file_path = os.path.join(frames_dir, file)
                    if os.path.isfile(file_path):
                        os.unlink(file_path)
            
            self.output_dir = frames_dir
            self.frames_dir = frames_dir  # 设置frames_dir属性
            
            # 获取视频总帧数用于计算进度
            total_frames = self.get_total_frames()
            if total_frames <= 0:
                self.log_message.emit("无法获取视频总帧数，将无法显示精确进度")
                total_frames = 1000  # 设置一个默认值
            
            # 构建FFmpeg命令
            command = [self.ffmpeg_path]
            
            # 添加硬件加速参数
            if self.hardware_accel != "cpu":
                # 提取实际的硬件加速类型（去除描述文本）
                actual_accel = self.hardware_accel.split()[0] if " " in self.hardware_accel else self.hardware_accel
                command.extend(["-hwaccel", actual_accel])
            
            # 添加输入文件
            command.extend(["-i", self.input_video])
            
            # 添加输出参数
            output_pattern = os.path.join(frames_dir, "%04d.jpg")
            command.extend(["-vf", f"fps={self.fps}", "-q:v", "1", "-y", output_pattern])
            
            self.log_message.emit(f"开始提取帧，帧率: {self.fps}")
            # 记录命令，处理路径中的空格和特殊字符
            command_str = " ".join(f'"{item}"' if ' ' in str(item) or '\\' in str(item) else str(item) for item in command)
            self.log_message.emit(f"FFmpeg命令: {command_str}")
            
            # 创建无窗口进程
            startupinfo = get_startupinfo()
            
            # 启动进程并实时获取输出
            process = subprocess.Popen(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                universal_newlines=True,
                startupinfo=startupinfo
            )
            
            # 读取输出并更新进度
            for line in process.stdout:
                if self.should_stop:
                    process.terminate()
                    self.log_message.emit("用户取消了帧提取")
                    self.process_completed.emit(False, "用户取消")
                    return
                
                # 输出日志
                self.log_message.emit(line.strip())
                
                # 尝试从输出中提取当前帧
                frame_match = re.search(r"frame=\s*(\d+)", line)
                if frame_match:
                    current_frame = int(frame_match.group(1))
                    progress = min(int(current_frame / total_frames * 100), 100)
                    self.progress_updated.emit(progress)
                    
                    # 每处理50帧或进度变化超过5%时输出进度日志
                    if current_frame % 50 == 0 or progress % 5 == 0:
                        self.log_message.emit(f"已处理 {current_frame}/{total_frames} 帧 ({progress}%)")
            
            # 等待进程完成
            return_code = process.wait()
            
            # 检查命令是否成功执行
            if return_code == 0:
                extracted_frames = len([f for f in os.listdir(frames_dir) if f.endswith('.jpg')])
                self.log_message.emit(f"帧提取完成，共 {extracted_frames} 帧")
                self.progress_updated.emit(100)
                self.process_completed.emit(True, "帧提取完成")
            else:
                self.log_message.emit(f"帧提取失败，返回码: {return_code}")
                
                # 如果是硬件加速失败，尝试使用CPU重试
                if self.hardware_accel != "cpu":
                    self.log_message.emit("硬件加速失败，尝试使用CPU重试...")
                    self.hardware_accel = "cpu"
                    self.extract_frames()
                    return
                
                self.process_completed.emit(False, "帧提取失败")
        
        except Exception as e:
            self.log_message.emit(f"帧提取出错: {str(e)}")
            self.log_message.emit(f"详细错误: {traceback.format_exc()}")
            self.process_completed.emit(False, f"帧提取出错: {str(e)}")
    
    def get_total_frames(self):
        """获取视频总帧数"""
        try:
            if not self.ffmpeg_path or not os.path.exists(self.input_video):
                return 0
            
            # 创建无窗口进程
            startupinfo = get_startupinfo()
            
            # 使用FFmpeg获取视频信息
            command = [
                self.ffmpeg_path,
                "-i", self.input_video,
                "-hide_banner"
            ]
            
            process = subprocess.Popen(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
                startupinfo=startupinfo
            )
            
            stdout, stderr = process.communicate()
            
            # 从输出中解析帧率和时长
            duration_match = re.search(r"Duration: (\d+):(\d+):(\d+)\.(\d+)", stderr)
            fps_match = re.search(r"(\d+(?:\.\d+)?) fps", stderr)
            
            if duration_match and fps_match:
                hours = int(duration_match.group(1))
                minutes = int(duration_match.group(2))
                seconds = int(duration_match.group(3))
                milliseconds = int(duration_match.group(4))
                
                total_seconds = hours * 3600 + minutes * 60 + seconds + milliseconds / 100
                fps = float(fps_match.group(1))
                
                return int(total_seconds * fps)
            
            return 0
        
        except Exception as e:
            self.log_message.emit(f"获取视频帧数出错: {str(e)}")
            return 0